﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DeployableProjectRepository.cs" company="Elilink">
//   Defor
// </copyright>
// <summary>
//   Class DeployableProjectRepository
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace DataAccessLayer.Repositories.Static
{
    using System.Collections.Generic;
    using System.Linq;

    using BusinessLayer.Enums;
    using BusinessLayer.Objects;
    using BusinessLayer.Results;

    using DataAccessLayer.Repositories.Abstract;
    using DataAccessLayer.StaticTools;

    /// <summary>
    ///     Class DeployableProjectRepository
    /// </summary>
    public class DeployableProjectRepository : IDeployableProjectRepository
    {
        #region Public Methods and Operators

        /// <summary>
        /// Adds the deployable project.
        /// </summary>
        /// <param name="project">
        /// The project.
        /// </param>
        /// <returns>
        /// The <see cref="BusinessLayer.Results.OperationResult"/>.
        /// </returns>
        public OperationResult AddDeployableProject(DeployableProject project)
        {
            return DeployableProjectOperations.AddDeployableProject(project);
        }

        /// <summary>
        ///     Deletes all projects for all target systems.
        /// </summary>
        /// ///
        /// <returns>The <see cref="BusinessLayer.Results.OperationResult" />.</returns>
        public OperationResult ClearAllDeployableProjects()
        {
            StaticDatabase.DeployableProjects.RemoveAll(p => true);
            return new OperationResult(true);
        }

        /// <summary>
        /// Deletes all projects for specified target system.
        /// </summary>
        /// <param name="targetSystem">
        /// The target system.
        /// </param>
        /// <returns>
        /// The <see cref="BusinessLayer.Results.OperationResult"/>.
        /// </returns>
        public OperationResult ClearDeployableProjectsForTargetSystem(string targetSystem)
        {
            StaticDatabase.DeployableProjects.RemoveAll(p => p.TargetSystemName == targetSystem);
            return new OperationResult(true);
        }

        /// <summary>
        /// Deletes the deployable project.
        /// </summary>
        /// <param name="projectName">
        /// Name of the project.
        /// </param>
        /// <param name="targetSystem">
        /// The target system.
        /// </param>
        /// <returns>
        /// The <see cref="BusinessLayer.Results.OperationResult"/>.
        /// </returns>
        public OperationResult DeleteDeployableProject(string projectName, string targetSystem)
        {
            DeployableProject old =
                StaticDatabase.DeployableProjects.FirstOrDefault(
                    p => p.ProjectName == projectName && p.TargetSystemName == targetSystem);
            if (old == null)
            {
                return new OperationResult(
                    ErrorType.ObjectNotFound, 
                    string.Format("Can't find project '{0}' in target '{1}'.", projectName, targetSystem));
            }

            StaticDatabase.DeployableProjects.Remove(old);
            return new OperationResult(true);
        }

        /// <summary>
        ///     Disposes the context.
        /// </summary>
        public void DisposeContext()
        {
            StaticDatabase.DeployableProjects.RemoveAll(p => true);
            StaticDatabase.TargetSystems.RemoveAll(t => true);
        }

        /// <summary>
        /// Gets the deployable projects.
        /// </summary>
        /// <param name="targetSystem">
        /// The target system.
        /// </param>
        /// <returns>
        /// List of <see cref="BusinessLayer.Objects.DeployableProject"/>.
        /// </returns>
        public List<DeployableProject> GetDeployableProjects(string targetSystem)
        {
            if (string.IsNullOrEmpty(targetSystem))
            {
                return StaticDatabase.DeployableProjects;
            }

            return StaticDatabase.DeployableProjects.Where(p => p.TargetSystemName == targetSystem).ToList();
        }

        /// <summary>
        /// Updates the deployable project (Password, ProjectPath, PublishProfile, UserName).
        /// </summary>
        /// <param name="project">
        /// The project.
        /// </param>
        /// <returns>
        /// The <see cref="BusinessLayer.Results.OperationResult"/>.
        /// </returns>
        public OperationResult UpdateDeployableProject(DeployableProject project)
        {
            DeployableProject old =
                StaticDatabase.DeployableProjects.FirstOrDefault(
                    p => p.ProjectName == project.ProjectName && p.TargetSystemName == project.TargetSystemName);
            if (old == null)
            {
                var message = string.Format(
                    "Can't find project '{0}' in target '{1}'.",
                    project.ProjectName,
                    project.TargetSystemName);
                return new OperationResult(
                    ErrorType.ObjectNotFound, message);
            }

            old.Password = project.Password;
            old.ProjectPath = project.ProjectPath;
            old.PublishProfile = project.PublishProfile;
            old.UserName = project.UserName;
            return new OperationResult(true);
        }

        /// <summary>
        /// Allows to completely update the deployable project.
        /// </summary>
        /// <param name="project">
        /// The project.
        /// </param>
        /// <param name="oldName">
        /// The old name.
        /// </param>
        /// <param name="oldTargetSystem">
        /// The target system.
        /// </param>
        /// <returns>
        /// The <see cref="BusinessLayer.Results.OperationResult"/>.
        /// </returns>
        public OperationResult UpdateDeployableProjectFull(
            DeployableProject project, 
            string oldName, 
            string oldTargetSystem)
        {
            DeployableProject old =
                StaticDatabase.DeployableProjects.FirstOrDefault(
                    p => p.ProjectName == oldName && p.TargetSystemName == oldTargetSystem);
            if (old == null)
            {
                return new OperationResult(
                    ErrorType.ObjectNotFound, 
                    string.Format("Can't find project '{0}' in target '{1}'.", oldName, oldTargetSystem));
            }

            if (string.IsNullOrEmpty(project.TargetSystemName))
            {
                return new OperationResult(
                    ErrorType.TargetSystemNameNotSpecified, 
                    "Can't update project without reference to target system.");
            }

            if (string.IsNullOrEmpty(project.ProjectName))
            {
                return new OperationResult(ErrorType.ProjectNameNotSpecified, "Can't update project without name.");
            }

            if (StaticDatabase.TargetSystems.FirstOrDefault(t => t.TargetSystemName == project.TargetSystemName) == null)
            {
                var message = string.Format(
                    "Can't find target '{1}' for updating project '{0}'.",
                    project.ProjectName,
                    project.TargetSystemName);
                return new OperationResult(
                    ErrorType.ObjectNotFound, message);
            }

            if (
                StaticDatabase.DeployableProjects.FirstOrDefault(
                    p => p.TargetSystemName == project.TargetSystemName && p.ProjectName == project.ProjectName) != null)
            {
                var message = string.Format(
                    "Project '{0}' already exists in target '{1}'.",
                    project.ProjectName,
                    project.TargetSystemName);
                return new OperationResult(
                    ErrorType.AlreadyExists, message);
            }

            old.ProjectName = project.ProjectName;
            old.Password = project.Password;
            old.ProjectPath = project.ProjectPath;
            old.PublishProfile = project.PublishProfile;
            old.UserName = project.UserName;
            old.TargetSystemName = project.TargetSystemName;
            return new OperationResult(true);
        }

        #endregion
    }
}